Imports System.Collections.Generic
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

Imports Vintasoft.Imaging
Imports Vintasoft.Imaging.VisualTools


Namespace Imaging
	''' <summary>
	''' The visual tool that allows to scroll the pages in the image viewer.
	''' </summary>
	Public Class ScrollPages
		Inherits VisualTool

		#Region "Enums"

		''' <summary>
		''' Specifies available scroll actions.
		''' </summary>
		Private Enum ScrollAction
			''' <summary>
			''' No action.
			''' </summary>
			None

			''' <summary>
			''' Move To Next Page action.
			''' </summary>
			MoveToNextPage

			''' <summary>
			''' Move ToPrevious Page action.
			''' </summary>
			MoveToPreviousPage
		End Enum

		#End Region



		#Region "Fields"

		''' <summary>
		''' A value indicating whether the page changing is in progress.
		''' </summary>
		Private _isPageChanging As Boolean

		''' <summary>
		''' The current scroll action.
		''' </summary>
		Private _scrollAction As ScrollAction = ScrollAction.None

		''' <summary>
		''' X coordinate of autoscroll position of previous focused image.
		''' </summary>
		Private _oldAutoScrollPositionX As Single

		''' <summary>
		''' Width of previous focused image.
		''' </summary>
		Private _oldImageWidth As Integer

		#End Region



		#Region "Constructors"

		''' <summary>
		''' Creates a new instance of the <see cref="ScrollPages"/> object.
		''' </summary>
		Public Sub New()
			MyBase.New()
			MyBase.Cursor = Cursors.Arrow
			MyBase.ActionCursor = MyBase.Cursor
		End Sub

		#End Region



		#Region "Properties"

		''' <summary>
		''' Gets the name of the visual tool.
		''' </summary>
		Public Overrides ReadOnly Property Name() As String
			Get
				Return "Scroll pages"
			End Get
		End Property

		Private _scrollStep As Integer = 10
		''' <summary>
		''' Gets or sets the scroll step size of this tool.
		''' </summary>
		Public Property ScrollStep() As Integer
			Get
				Return _scrollStep
			End Get
			Set
				If value > 100 Then
					value = 100
				End If
				If value < 0 Then
					value = 0
				End If
				_scrollStep = value
			End Set
		End Property

		#End Region



		#Region "Methods"

		#Region "PROTECTED"

		''' <summary>
		''' Raises the MouseMove event.
		''' </summary>
		''' <param name="e">A MouseEventArgs that contains the event data.</param>
		Protected Overrides Sub OnMouseMove(e As MouseEventArgs)
			If Not Enabled Then
				Return
			End If

			ImageViewer.Cursor = MyBase.Cursor

			MyBase.OnMouseMove(e)
		End Sub

		''' <summary>
		''' Raises the MouseWheel event.
		''' </summary>
		''' <param name="e">A MouseEventArgs that contains the event data.</param>
		''' <param name="handled">Indicates whether the event was handled.</param>
		Protected Overrides Sub OnMouseWheel(e As MouseEventArgs, ByRef handled As Boolean)
			handled = False

			If Not Enabled Then
				Return
			End If

			If _isPageChanging Then
				Return
			End If

			Scroll(e)

			handled = True
		End Sub

		#End Region


		#Region "PRIVATE"

		''' <summary>
		''' Scrolls the current page.
		''' </summary>
		''' <param name="e">A MouseEventArgs that contains the event data.</param>
		Private Sub Scroll(e As MouseEventArgs)
			If Not Enabled Then
				Return
			End If

			Dim delta As Integer = e.Delta

			If delta <= 0 Then
				ScrollDown(_scrollStep)
			Else
				ScrollUp(_scrollStep)
			End If
		End Sub

		''' <summary>
		''' Scrolls the current page up.
		''' </summary>
		''' <param name="delta">A scroll step size.</param>
		Private Sub ScrollUp(delta As Integer)
			Dim autoScrollPosition As PointF = ImageViewer.ViewerState.AutoScrollPosition

			If autoScrollPosition.Y <= 0 Then
				If ImageViewer.FocusedIndex > 0 Then
					_isPageChanging = True
					_scrollAction = ScrollAction.MoveToPreviousPage
					_oldAutoScrollPositionX = autoScrollPosition.X
					_oldImageWidth = ImageViewer.Image.Width
					AddHandler ImageViewer.ImageLoading, New EventHandler(Of ImageLoadingEventArgs)(AddressOf ImageViewer_ImageLoading)
					ImageViewer.FocusedIndex -= 1
				End If
			Else
				UpdateAutoScrollPosition(-delta)
			End If
		End Sub

		''' <summary>
		''' Scrolls the current page down.
		''' </summary>
		''' <param name="delta">A scroll step size.</param>
		Private Sub ScrollDown(delta As Integer)
			Dim autoScrollPosition As PointF = ImageViewer.ViewerState.AutoScrollPosition
			Dim autoScrollSize As Size = ImageViewer.ViewerState.AutoScrollSize

			If Math.Round(autoScrollPosition.Y) >= autoScrollSize.Height Then
				If ImageViewer.FocusedIndex < ImageViewer.Images.Count - 1 Then
					_isPageChanging = True
					_scrollAction = ScrollAction.MoveToNextPage
					_oldAutoScrollPositionX = autoScrollPosition.X
					_oldImageWidth = ImageViewer.Image.Width
					AddHandler ImageViewer.ImageLoading, New EventHandler(Of ImageLoadingEventArgs)(AddressOf ImageViewer_ImageLoading)
					ImageViewer.FocusedIndex += 1
				End If
			Else
				UpdateAutoScrollPosition(delta)
			End If
		End Sub

		''' <summary>
		''' Updates the current page autoscroll position.
		''' </summary>
		''' <param name="delta">Step size for Y coord.</param>
		Private Sub UpdateAutoScrollPosition(delta As Integer)
			Dim x As Single = ImageViewer.ViewerState.AutoScrollPosition.X
			Dim y As Single = ImageViewer.ViewerState.AutoScrollPosition.Y
			UpdateAutoScrollPosition(x, y + delta)
		End Sub

		''' <summary>
		''' Updates the current page autoscroll position.
		''' </summary>
		''' <param name="x">X coord.</param>
		''' <param name="y">Y coord.</param>
		Private Sub UpdateAutoScrollPosition(x As Single, y As Single)
			ImageViewer.ViewerState.AutoScrollPosition = New PointF(x, y)
		End Sub

		''' <summary>
		''' Handler of the ImageLoading event of the image viewer.
		''' </summary>
		''' <param name="sender"></param>
		''' <param name="e"></param>
		Private Sub ImageViewer_ImageLoading(sender As Object, e As ImageLoadingEventArgs)
			If _scrollAction <> ScrollAction.None Then
				RemoveHandler ImageViewer.ImageLoading, New EventHandler(Of ImageLoadingEventArgs)(AddressOf ImageViewer_ImageLoading)

				Dim autoScrollPositionX As Single
				Dim autoScrollPositionY As Single

				' autoScrollPositionX
				If True Then
					Dim proportion As Single = CSng(ImageViewer.Image.Width) / _oldImageWidth
					autoScrollPositionX = _oldAutoScrollPositionX * proportion
				End If

				' autoScrollPositionY
				Select Case _scrollAction
					Case ScrollAction.MoveToNextPage
						autoScrollPositionY = 0
						Exit Select
					Case ScrollAction.MoveToPreviousPage
						autoScrollPositionY = ImageViewer.ViewerState.AutoScrollSize.Height
						Exit Select
					Case Else
						Throw New Exception()
				End Select

				UpdateAutoScrollPosition(autoScrollPositionX, autoScrollPositionY)
				_scrollAction = ScrollAction.None
			End If

			_isPageChanging = False
		End Sub

		#End Region

		#End Region

	End Class
End Namespace
